package org.snaker.engine.parser.logicflow;

import org.apache.commons.collections.CollectionUtils;
import org.snaker.engine.SnakerEngine;
import org.snaker.engine.helper.JsonHelper;
import org.snaker.engine.model.NodeModel;
import org.snaker.engine.model.ProcessModel;
import org.snaker.engine.model.TransitionModel;
import org.snaker.engine.parser.AbstractModelParser;
import org.snaker.engine.parser.NodeParser;
import org.snaker.engine.parser.NodeParserProvider;
import org.snaker.engine.parser.logicflow.model.LogicFlowData;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.snaker.engine.parser.NodeParser.ATTR_EXPR;

/**
 * LogicFlow 定义的模型解析器
 */
public class LogicFlowModelParser extends AbstractModelParser<LogicFlowData.Node> {

    private static final String NODE_NAME_PREFIX = "snaker:";


    public LogicFlowModelParser(NodeParserProvider<LogicFlowData.Node> nodeParserProvider) {
        super(nodeParserProvider);
    }

    @Override
    protected NodeModel parseModel(LogicFlowData.Node node) {
        String type = node.getType().replaceAll(NODE_NAME_PREFIX, "");

        NodeParser<LogicFlowData.Node> nodeParser = nodeParserProvider.getByName(type);
        nodeParser.parse(node);
        return nodeParser.getNodeModel();
    }

    /**
     * 获取节点输出
     *
     * @param sourceNodeId 源节点id
     * @param edges
     * @return
     */
    private List<LogicFlowData.Line> getEdgeBySourceNodeId(String sourceNodeId, List<LogicFlowData.Line> edges) {
        return edges.stream().filter(edge -> edge.getSourceNodeId().equals(sourceNodeId)).collect(Collectors.toList());
    }

    @Override
    public ProcessModel parse(byte[] bytes) {
        LogicFlowData data = JsonHelper.fromJson(bytes, LogicFlowData.class);
        ProcessModel process = new ProcessModel();
        List<LogicFlowData.Node> nodes = data.getNodes();
        List<LogicFlowData.Line> edges = data.getEdges();
        if (CollectionUtils.isEmpty(nodes) || CollectionUtils.isEmpty(edges)) {
            throw new IllegalArgumentException("model is invalid");
        }

        // 流程定义基本信息
        process.setName(data.getName());
        process.setDisplayName(data.getDisplayName());
        process.setInstanceUrl(data.getInstanceUrl());
        process.setInstanceNoClass(data.getInstanceNoClass());
        for (LogicFlowData.Node node : nodes) {
            NodeModel model = parseModel(node);
            model.setOutputs(getEdgeBySourceNodeId(node.getId(), edges).stream().map(line -> {
                TransitionModel transition = new TransitionModel();
                transition.setName(line.getId());
                if(Objects.nonNull(line.getText())) {
                    transition.setDisplayName(line.getText().getValue());
                }
                transition.setTo(line.getTargetNodeId());
                transition.setExpr(line.getProperties().get(ATTR_EXPR));
                transition.setG(line.getG());
                transition.setOffset("0,0");
                transition.setSource(model);
                return transition;
            }).collect(Collectors.toList()));
            process.getNodes().add(model);
        }

        //循环节点模型，构造变迁输入、输出的source、target
        for (NodeModel node : process.getNodes()) {
            for (TransitionModel transition : node.getOutputs()) {
                String to = transition.getTo();
                for (NodeModel node2 : process.getNodes()) {
                    if (to.equalsIgnoreCase(node2.getName())) {
                        node2.getInputs().add(transition);
                        transition.setTarget(node2);
                    }
                }
            }
        }
        return process;
    }
}
